﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Compiler
{

    class Commands
    {

        public CompilerData CompilerDataobj;
        public List<string> usererror_list;
        public UserData UserDataobj;
        private string current_symbol;
        int currentwordnum;
        string temp_symbol;
        public Commands(string commandcode)
        {
            currentwordnum = 0;
            usererror_list = new List<string>();
            UserDataobj = new UserData();
            CompilerDataobj = new CompilerData();
           
            UserDataobj.UserCode = commandcode.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList<string>();
            UserDataobj.incrementLinenum();
           
        }

        public Commands()
        {
            // TODO: Complete member initialization
        }

        int is_curr_symbol_reservedword()//seaches and returns index of it if found
        {
            for (int i = 0; i < CompilerDataobj.ReservedWords.Count; i++)
            {
                if (temp_symbol == CompilerDataobj.ReservedWords[i])
                    return i;
            }
            return -1;  //not found
        }

        int is_DataType()//seaches and returns index of it if found
        {
            for (int i = 0; i < CompilerDataobj.DataTypes.Count; i++)
            {
                if (temp_symbol == CompilerDataobj.DataTypes[i])
                    return i;
            }
            return -1;  //not found
        }
        bool is_currsym_operator(string sym,List<string> list)

        {
            int listcount = list.Count;
            for (int i = 0; i < listcount; i++)
            {
                if (sym== list[i])
                    return true;
            }

            return false;
             
         }

        //get symbol from the user code stream 
        int  get_symbol(bool declaration_step)
        {
            temp_symbol = UserDataobj.Currentline[currentwordnum].ToLower();
            if (++currentwordnum == (UserDataobj.Currentline.Count))  //end of 1st line
            {
                UserDataobj.incrementLinenum();  //get next line
                currentwordnum=0;
            }
            //check for this symbol what it is

            //check if it is reserved word
            if ((temp_symbol[0] >= 65 && temp_symbol[0] <= 90) || (temp_symbol[0] >= 97 && temp_symbol[0] <= 122))
            {
                if (is_curr_symbol_reservedword() != -1)
                    current_symbol = temp_symbol;
                else if (is_DataType() != -1)
                    current_symbol = temp_symbol;

                else //identifier
                {
                    if (!declaration_step)
                    {
                        if (identifier_previously_declared(temp_symbol, UserDataobj.IdentiferList))
                        {
                            current_symbol = "ident";       //identifier
                        }
                        else
                        {
                            return 11;
                        
                        }
                    }
                    else
                    {
                        //check if it exits before 
                        if (identifier_previously_declared(temp_symbol, UserDataobj.IdentiferList))
                            return 5;  //syntax error declared before 
                        else
                        {
                            UserDataobj.IdentiferList.Add(temp_symbol);
                            current_symbol = "ident";
                        }


                    }
                }//end of else that identifier

            }//

            else   //check if number or operator
            {
                    if(temp_symbol[0]>='0' &&  temp_symbol[0]<='9') //
                    {
                        for(int i=1;i<temp_symbol.Length;i++)
                        {
                            if(!(temp_symbol[0]>='0' &&  temp_symbol[0]<='9'))
                             {      
                                current_symbol="notnumber";
                                return 8; // unknow identifier 
                            }
                            else 
                            current_symbol="number";
                        }
                        current_symbol = "number";
                    }
                    else if (temp_symbol[0]=='"')         //check if string 

                    {
                        if(temp_symbol[temp_symbol.Length-1]=='"')  //string 
                        {
                            current_symbol="stringsym"; //????
                        }
                        else 
                        {
                            current_symbol="notstring";
                            return 7; //sytax srror bad close of the string end
                        }
                    }
                    else if(is_currsym_operator(temp_symbol,CompilerDataobj.operator_signs))// check if operator
                        current_symbol=temp_symbol;
                    else  //unknown
                    {
                        current_symbol="unknown";
                        return 8 ; //sytax error unknown identifier

                    }
            }



            
            return 0;  //no errors
        }

        public int CheckCode()
        {
            return checkProgram();

        }
        int Robot()
        {
            int x=Accept(CompilerDataobj.ReservedWords[0],false);
            if (x == 0)
            {
                x = Accept("ident", true);
                if (x == 0)
                {
                    x = block();
                    if (x == 0)
                    {
                        x = Accept(CompilerDataobj.ReservedWords[1], false);
                      //  UserDataobj.IdentiferList.Add(CompilerDataobj.ReservedWords[1]);
                    }
                }
            }
            return x; 
        }
         
        int statements()
        {
            int x = Assignment_Statment();
            if (x == 0)
            {
                x = commandStatment();
            }
            return x;
        int block()
        {
            int x = declaration();
            if (x == 0)
            {
                x = statements();
            }
            else
                return x;
           

            return x;
        }
        
        private int declaration()
        {
            int ErrorNum =0;
            do
            {
                 ErrorNum = Accept("char", false);
                if (ErrorNum != 0 || ErrorNum == -1 )
                {
                    if (current_symbol == "byte")
                        ErrorNum = 0;
                    else
                    {
                        ErrorNum = 0;
                        break;
                    }
                }

                if (ErrorNum == 0)
                {
                   ErrorNum= Accept("ident", true);
                    
                }

            } while (true);

            return ErrorNum;
            

        }

        int commandStatment()
        {
            int ErrorNum =-1;
            do
	        {
	         
                get_symbol ( false);
                switch (current_symbol)
	            {
                    case "if" :
                        ErrorNum = If_statment();
                       
                        break;
                   
                    case "for" :
                            ErrorNum = For_statment();
                        break;
                    case "print" :
                            ErrorNum =Print_statment();
                        break;
		            default:
                        break;
	            }

                if ( ErrorNum !=0)
                {
                    return ErrorNum;
                }

	        } while (true);          return ErrorNum;

        }

private int Print_statment()
{
 	throw new NotImplementedException();
}

private int For_statment()
{
 	throw new NotImplementedException();
}

private int If_statment()
{
 	throw new NotImplementedException();
}
        private int Assignment_Statment()
        {
            int ErrorNum = -1;
            if (current_symbol == "ident")  // ident 
                ErrorNum = 0;
            if (ErrorNum == 0)
            {
                ErrorNum = Accept("=", false);             // ident = 
                if (ErrorNum == 0)
                {
                    ErrorNum = Accept("ident", false);      // ident = ident
                    if (ErrorNum == 0)
                    {
                        return 0;
                    }
                    else
                    {
                        if (current_symbol == "number")   // ident = digit
                            ErrorNum = 0;  
                        if (ErrorNum == 0)
                        {
                            return 0;
                        }
                        else
                        {
                            if (current_symbol == "letter")// ident = letter
                                ErrorNum = 0;
                            if (ErrorNum == 0)
                            {
                                return 0;
                            }
                        
                        }

                    }
                }

                return 10;
            }

            return 0;
        }

        
        int checkProgram()
        {
           int x= Robot();
           
                return x;
        }
        int Accept(string symbol,bool declartionstep)
        {
            if (!declartionstep)
            {
              int ErrorNum = get_symbol(false);
              if (current_symbol == symbol)
              {
                  return 0; //token as expected
              }
              else
              {
                  if (ErrorNum == 0)
                      return -1;
                  
                  return ErrorNum;
              }
            }
            else
            {
                int x = get_symbol(true);
                    if(x!=0)
                        return x; //syntax error declard before
            }
           return 0;
        }

        
        private int checkBlock()
        {
            while (UserDataobj.Currentline.Count == 0)
            {
                UserDataobj.incrementLinenum();
            }
            return 0;
        }

        //private int AcceptIdentifer(string Identifer)
        //{
        //    // Identifer is word which does not exist in Iderntifer list and tokens list
        //    if( NotInsideList(Identifer ,CompilerDataobj.ReservedWords) )
        //    {
        //        UserDataobj.IdentiferList.Add(Identifer);
        //        return 0;
        //    }

        //    return 3;
        //}

        private bool identifier_previously_declared(string Word , List<string> list)
        { 
            int listcount= list.Count;
            for (int i = 0; i < listcount; i++)
            {
                if (Word.ToLower() == list[i].ToLower())
                    return true;
            }

            return false;
            
        }

        private int AcceptWord(string userinput, string reservedWord)
        {
            if (userinput.ToLower() == reservedWord.ToLower())
            {
                UserDataobj.Usertokens.Add(reservedWord);
                return 0;
            }
            else
                return 1; 
        }

    }
}
 